/*
 * Audio FSK modem for AX25 (1200 Baud, 1200/2200Hz).
 * 
 * Copyright (C) Sivan Toledo, 2012
 * 
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package obsolete;

import java.util.Arrays;

import sivantoledo.ax25.Afsk1200Filters;
import sivantoledo.ax25.Filter;
import sivantoledo.ax25.Packet;
import sivantoledo.ax25.PacketHandler;

public class XXXAfsk1200 implements XXXHalfduplexSoundcardClient {
/*	
	// Matlab-generated constants
  private static final int[] sample_rates = { 9600, 12000, 11025, 22050, 24000, 44100, 48000 };
  private static final int[] bit_periods = { 8, 10, 9, 18, 20, 36, 40 };
  // firls(filter_length,[0 1050 1150 2250 2350 r_nyquist(r)]/r_nyquist(r) ...
  //                    ,[0    0    1    1    0     0]);
  private static final float[][] time_domain_filter_old = {
    { -1.322927e-001f, -1.988392e-001f, -2.157701e-002f, 2.149272e-001f, 2.149272e-001f, -2.157701e-002f, -1.988392e-001f, -1.322927e-001f, },
    { -9.236515e-002f, -1.629263e-001f, -1.095414e-001f, 4.677393e-002f, 1.830927e-001f, 1.830927e-001f, 4.677393e-002f, -1.095414e-001f, -1.629263e-001f, -9.236515e-002f, },
    { -1.172307e-001f, -1.773430e-001f, -7.168043e-002f, 1.235695e-001f, 2.215638e-001f, 1.235695e-001f, -7.168043e-002f, -1.773430e-001f, -1.172307e-001f, },
    { -4.237994e-002f, -7.231490e-002f, -8.829450e-002f, -8.343683e-002f, -5.639939e-002f, -1.234070e-002f, 3.816670e-002f, 8.202517e-002f, 1.074341e-001f, 1.074341e-001f, 8.202517e-002f, 3.816670e-002f, -1.234070e-002f, -5.639939e-002f, -8.343683e-002f, -8.829450e-002f, -7.231490e-002f, -4.237994e-002f, },
    { -3.191234e-002f, -5.898512e-002f, -7.743270e-002f, -8.133593e-002f, -6.786161e-002f, -3.832265e-002f, 1.836228e-003f, 4.418395e-002f, 7.931214e-002f, 9.918340e-002f, 9.918340e-002f, 7.931214e-002f, 4.418395e-002f, 1.836228e-003f, -3.832265e-002f, -6.786161e-002f, -8.133593e-002f, -7.743270e-002f, -5.898512e-002f, -3.191234e-002f, },
    { -1.690962e-002f, -2.531364e-002f, -3.288043e-002f, -3.897437e-002f, -4.302926e-002f, -4.459873e-002f, -4.339902e-002f, -3.933998e-002f, -3.254120e-002f, -2.333160e-002f, -1.223179e-002f, 7.965794e-005f, 1.281359e-002f, 2.512772e-002f, 3.618949e-002f, 4.523934e-002f, 5.164907e-002f, 5.497053e-002f, 5.497053e-002f, 5.164907e-002f, 4.523934e-002f, 3.618949e-002f, 2.512772e-002f, 1.281359e-002f, 7.965794e-005f, -1.223179e-002f, -2.333160e-002f, -3.254120e-002f, -3.933998e-002f, -4.339902e-002f, -4.459873e-002f, -4.302926e-002f, -3.897437e-002f, -3.288043e-002f, -2.531364e-002f, -1.690962e-002f, },
    { -1.230762e-002f, -1.953642e-002f, -2.636505e-002f, -3.232989e-002f, -3.699264e-002f, -3.997223e-002f, -4.097406e-002f, -3.981434e-002f, -3.643759e-002f, -3.092578e-002f, -2.349828e-002f, -1.450233e-002f, -4.394465e-003f, 6.286047e-003f, 1.694991e-002f, 2.699461e-002f, 3.584277e-002f, 4.297935e-002f, 4.798524e-002f, 5.056464e-002f, 5.056464e-002f, 4.798524e-002f, 4.297935e-002f, 3.584277e-002f, 2.699461e-002f, 1.694991e-002f, 6.286047e-003f, -4.394465e-003f, -1.450233e-002f, -2.349828e-002f, -3.092578e-002f, -3.643759e-002f, -3.981434e-002f, -4.097406e-002f, -3.997223e-002f, -3.699264e-002f, -3.232989e-002f, -2.636505e-002f, -1.953642e-002f, -1.230762e-002f, }
  };
  // Here we add a bit of emphasis to the high tones to counter aggressive de-emphasis
  // r_b{r}=firls(filter_length,[0 1050 1150 2250 2350 r_nyquist(r)]/r_nyquist(r) ...
  //                           ,[0    0 0.75    1    0     0]);  
  private static final float[][] time_domain_filter_x1 = {
    { -1.082658e-001f, -1.769969e-001f, -2.427756e-002f, 1.870885e-001f, 1.870885e-001f, -2.427756e-002f, -1.769969e-001f, -1.082658e-001f, },
    { -7.402586e-002f, -1.427611e-001f, -1.003370e-001f, 3.751086e-002f, 1.597027e-001f, 1.597027e-001f, 3.751086e-002f, -1.003370e-001f, -1.427611e-001f, -7.402586e-002f, },
    { -9.625001e-002f, -1.569615e-001f, -6.774629e-002f, 1.058392e-001f, 1.938783e-001f, 1.058392e-001f, -6.774629e-002f, -1.569615e-001f, -9.625001e-002f, },
    { -3.301012e-002f, -6.113652e-002f, -7.723162e-002f, -7.465092e-002f, -5.181335e-002f, -1.316443e-002f, 3.177878e-002f, 7.108044e-002f, 9.392786e-002f, 9.392786e-002f, 7.108044e-002f, 3.177878e-002f, -1.316443e-002f, -5.181335e-002f, -7.465092e-002f, -7.723162e-002f, -6.113652e-002f, -3.301012e-002f, },
    { -2.383452e-002f, -4.903209e-002f, -6.698512e-002f, -7.204288e-002f, -6.134941e-002f, -3.587299e-002f, -4.324651e-004f, 3.733953e-002f, 6.885008e-002f, 8.672631e-002f, 8.672631e-002f, 6.885008e-002f, 3.733953e-002f, -4.324651e-004f, -3.587299e-002f, -6.134941e-002f, -7.204288e-002f, -6.698512e-002f, -4.903209e-002f, -2.383452e-002f, },
    { -1.256970e-002f, -2.032736e-002f, -2.743701e-002f, -3.330157e-002f, -3.738317e-002f, -3.925104e-002f, -3.862225e-002f, -3.539176e-002f, -2.964852e-002f, -2.167607e-002f, -1.193710e-002f, -1.042795e-003f, 1.029075e-002f, 2.129557e-002f, 3.121016e-002f, 3.933821e-002f, 4.510297e-002f, 4.809256e-002f, 4.809256e-002f, 4.510297e-002f, 3.933821e-002f, 3.121016e-002f, 2.129557e-002f, 1.029075e-002f, -1.042795e-003f, -1.193710e-002f, -2.167607e-002f, -2.964852e-002f, -3.539176e-002f, -3.862225e-002f, -3.925104e-002f, -3.738317e-002f, -3.330157e-002f, -2.743701e-002f, -2.032736e-002f, -1.256970e-002f, },
    { -8.585801e-003f, -1.521102e-002f, -2.156690e-002f, -2.722002e-002f, -3.175674e-002f, -3.481332e-002f, -3.610372e-002f, -3.544294e-002f, -3.276397e-002f, -2.812701e-002f, -2.172006e-002f, -1.385059e-002f, -4.928699e-003f, 4.557173e-003f, 1.407051e-002f, 2.306079e-002f, 3.099913e-002f, 3.741291e-002f, 4.191699e-002f, 4.423938e-002f, 4.423938e-002f, 4.191699e-002f, 3.741291e-002f, 3.099913e-002f, 2.306079e-002f, 1.407051e-002f, 4.557173e-003f, -4.928699e-003f, -1.385059e-002f, -2.172006e-002f, -2.812701e-002f, -3.276397e-002f, -3.544294e-002f, -3.610372e-002f, -3.481332e-002f, -3.175674e-002f, -2.722002e-002f, -2.156690e-002f, -1.521102e-002f, -8.585801e-003f, }
  };
  
  // r_b{r}=firls(filter_length,[0 1050 1150 2250 2350 r_nyquist(r)]/r_nyquist(r) ...
  //                           ,[0    0 0.33    1    0     0]);  
  private static final float[][] time_domain_filter_x2 = {
    { -6.790074e-002f, -1.403020e-001f, -2.881449e-002f, 1.403196e-001f, 1.403196e-001f, -2.881449e-002f, -1.403020e-001f, -6.790074e-002f, },
    { -4.321584e-002f, -1.088836e-001f, -8.487353e-002f, 2.194891e-002f, 1.204076e-001f, 1.204076e-001f, 2.194891e-002f, -8.487353e-002f, -1.088836e-001f, -4.321584e-002f, },
    { -6.100236e-002f, -1.227206e-001f, -6.113694e-002f, 7.605218e-002f, 1.473666e-001f, 7.605218e-002f, -6.113694e-002f, -1.227206e-001f, -6.100236e-002f, },
    { -1.726884e-002f, -4.235686e-002f, -5.864598e-002f, -5.989060e-002f, -4.410881e-002f, -1.454829e-002f, 2.104706e-002f, 5.269328e-002f, 7.123729e-002f, 7.123729e-002f, 5.269328e-002f, 2.104706e-002f, -1.454829e-002f, -4.410881e-002f, -5.989060e-002f, -5.864598e-002f, -4.235686e-002f, -1.726884e-002f, },
    { -1.026380e-002f, -3.231100e-002f, -4.943318e-002f, -5.643054e-002f, -5.040891e-002f, -3.175756e-002f, -4.243870e-003f, 2.584090e-002f, 5.127382e-002f, 6.579839e-002f, 6.579839e-002f, 5.127382e-002f, 2.584090e-002f, -4.243870e-003f, -3.175756e-002f, -5.040891e-002f, -5.643054e-002f, -4.943318e-002f, -3.231100e-002f, -1.026380e-002f, },
    { -5.278626e-003f, -1.195040e-002f, -1.829207e-002f, -2.377126e-002f, -2.789775e-002f, -3.026691e-002f, -3.059728e-002f, -2.875877e-002f, -2.478881e-002f, -1.889477e-002f, -1.144203e-002f, -2.928517e-003f, 6.052378e-003f, 1.485757e-002f, 2.284489e-002f, 2.942432e-002f, 3.410552e-002f, 3.653758e-002f, 3.653758e-002f, 3.410552e-002f, 2.942432e-002f, 2.284489e-002f, 1.485757e-002f, 6.052378e-003f, -2.928517e-003f, -1.144203e-002f, -1.889477e-002f, -2.478881e-002f, -2.875877e-002f, -3.059728e-002f, -3.026691e-002f, -2.789775e-002f, -2.377126e-002f, -1.829207e-002f, -1.195040e-002f, -5.278626e-003f, },
    { -2.333142e-003f, -7.944358e-003f, -1.350601e-002f, -1.863545e-002f, -2.296044e-002f, -2.614635e-002f, -2.792155e-002f, -2.809898e-002f, -2.659229e-002f, -2.342509e-002f, -1.873266e-002f, -1.275565e-002f, -5.826211e-003f, 1.652663e-003f, 9.233113e-003f, 1.645198e-002f, 2.286183e-002f, 2.806127e-002f, 3.172233e-002f, 3.361295e-002f, 3.361295e-002f, 3.172233e-002f, 2.806127e-002f, 2.286183e-002f, 1.645198e-002f, 9.233113e-003f, 1.652663e-003f, -5.826211e-003f, -1.275565e-002f, -1.873266e-002f, -2.342509e-002f, -2.659229e-002f, -2.809898e-002f, -2.792155e-002f, -2.614635e-002f, -2.296044e-002f, -1.863545e-002f, -1.350601e-002f, -7.944358e-003f, -2.333142e-003f, }
  };

  // r_b{r}=firls(filter_length,[0  900 1200 2200 2500 r_nyquist(r)]/r_nyquist(r) ...
  //                           ,[0    0 0.25    1    0     0]);  
  private static final float[][] time_domain_filter_x3 = {
    { -6.112041e-002f, -1.380107e-001f, -2.874278e-002f, 1.472463e-001f, 1.472463e-001f, -2.874278e-002f, -1.380107e-001f, -6.112041e-002f, },
    { -3.774313e-002f, -1.053352e-001f, -8.542120e-002f, 2.316324e-002f, 1.264377e-001f, 1.264377e-001f, 2.316324e-002f, -8.542120e-002f, -1.053352e-001f, -3.774313e-002f, },
    { -5.488906e-002f, -1.200948e-001f, -6.179990e-002f, 7.970223e-002f, 1.548494e-001f, 7.970223e-002f, -6.179990e-002f, -1.200948e-001f, -5.488906e-002f, },
    { -1.433294e-002f, -3.919351e-002f, -5.662365e-002f, -5.941997e-002f, -4.459884e-002f, -1.484315e-002f, 2.199165e-002f, 5.523926e-002f, 7.487850e-002f, 7.487850e-002f, 5.523926e-002f, 2.199165e-002f, -1.484315e-002f, -4.459884e-002f, -5.941997e-002f, -5.662365e-002f, -3.919351e-002f, -1.433294e-002f, },
    { -7.815170e-003f, -2.928398e-002f, -4.705990e-002f, -5.534958e-002f, -5.050004e-002f, -3.229525e-002f, -4.287254e-003f, 2.699576e-002f, 5.377220e-002f, 6.916745e-002f, 6.916745e-002f, 5.377220e-002f, 2.699576e-002f, -4.287254e-003f, -3.229525e-002f, -5.050004e-002f, -5.534958e-002f, -4.705990e-002f, -2.928398e-002f, -7.815170e-003f, },
    { -3.949452e-003f, -1.034662e-002f, -1.664108e-002f, -2.227210e-002f, -2.669990e-002f, -2.945611e-002f, -3.018983e-002f, -2.870472e-002f, -2.498333e-002f, -1.919600e-002f, -1.169298e-002f, -2.980090e-003f, 6.320218e-003f, 1.551918e-002f, 2.391895e-002f, 3.087163e-002f, 3.583482e-002f, 3.841838e-002f, 3.841838e-002f, 3.583482e-002f, 3.087163e-002f, 2.391895e-002f, 1.551918e-002f, 6.320218e-003f, -2.980090e-003f, -1.169298e-002f, -1.919600e-002f, -2.498333e-002f, -2.870472e-002f, -3.018983e-002f, -2.945611e-002f, -2.669990e-002f, -2.227210e-002f, -1.664108e-002f, -1.034662e-002f, -3.949452e-003f, },
    { -1.268771e-003f, -6.559619e-003f, -1.198172e-002f, -1.714165e-002f, -2.164046e-002f, -2.510431e-002f, -2.721442e-002f, -2.773390e-002f, -2.652924e-002f, -2.358449e-002f, -1.900690e-002f, -1.302326e-002f, -5.967039e-003f, 1.742908e-003f, 9.630560e-003f, 1.719582e-002f, 2.394998e-002f, 2.945089e-002f, 3.333503e-002f, 3.534414e-002f, 3.534414e-002f, 3.333503e-002f, 2.945089e-002f, 2.394998e-002f, 1.719582e-002f, 9.630560e-003f, 1.742908e-003f, -5.967039e-003f, -1.302326e-002f, -1.900690e-002f, -2.358449e-002f, -2.652924e-002f, -2.773390e-002f, -2.721442e-002f, -2.510431e-002f, -2.164046e-002f, -1.714165e-002f, -1.198172e-002f, -6.559619e-003f, -1.268771e-003f, }
  };

  
  // fir1(filter_length,2250/r_nyquist(r)); (2250 is basically a typo)
  private static final float[][] corr_diff_filter_2250lp = {
    { -6.651761e-003f, -1.676162e-002f, 1.107302e-001f, 4.126832e-001f, 4.126832e-001f, 1.107302e-001f, -1.676162e-002f, -6.651761e-003f, },
    { -4.736690e-003f, -1.428261e-002f, 1.150588e-002f, 1.613335e-001f, 3.461799e-001f, 3.461799e-001f, 1.613335e-001f, 1.150588e-002f, -1.428261e-002f, -4.736690e-003f, },
    { -5.887073e-003f, -1.493580e-002f, 4.741476e-002f, 2.670217e-001f, 4.127728e-001f, 2.670217e-001f, 4.741476e-002f, -1.493580e-002f, -5.887073e-003f, },
    { -2.223118e-003f, -4.703188e-003f, -8.397949e-003f, -7.292353e-003f, 8.948891e-003f, 4.746144e-002f, 1.042481e-001f, 1.624451e-001f, 1.995131e-001f, 1.995131e-001f, 1.624451e-001f, 1.042481e-001f, 4.746144e-002f, 8.948891e-003f, -7.292353e-003f, -8.397949e-003f, -4.703188e-003f, -2.223118e-003f, },
    { -1.700973e-003f, -3.761089e-003f, -7.190483e-003f, -8.962287e-003f, -2.423359e-003f, 1.927810e-002f, 5.814876e-002f, 1.079310e-001f, 1.549870e-001f, 1.836933e-001f, 1.836933e-001f, 1.549870e-001f, 1.079310e-001f, 5.814876e-002f, 1.927810e-002f, -2.423359e-003f, -8.962287e-003f, -7.190483e-003f, -3.761089e-003f, -1.700973e-003f, },
    { -9.068200e-004f, -1.412275e-003f, -2.170772e-003f, -3.177507e-003f, -4.228859e-003f, -4.907084e-003f, -4.618321e-003f, -2.682521e-003f, 1.537974e-003f, 8.494267e-003f, 1.831979e-002f, 3.074066e-002f, 4.504978e-002f, 6.015587e-002f, 7.470450e-002f, 8.725428e-002f, 9.647984e-002f, 1.013672e-001f, 1.013672e-001f, 9.647984e-002f, 8.725428e-002f, 7.470450e-002f, 6.015587e-002f, 4.504978e-002f, 3.074066e-002f, 1.831979e-002f, 8.494267e-003f, 1.537974e-003f, -2.682521e-003f, -4.618321e-003f, -4.907084e-003f, -4.228859e-003f, -3.177507e-003f, -2.170772e-003f, -1.412275e-003f, -9.068200e-004f, },
    { -6.701787e-004f, -1.093916e-003f, -1.701677e-003f, -2.527634e-003f, -3.493032e-003f, -4.384841e-003f, -4.860297e-003f, -4.479895e-003f, -2.766156e-003f, 7.195035e-004f, 6.293470e-003f, 1.407404e-002f, 2.392656e-002f, 3.544079e-002f, 4.794695e-002f, 6.057111e-002f, 7.232418e-002f, 8.221322e-002f, 8.935974e-002f, 9.310808e-002f, 9.310808e-002f, 8.935974e-002f, 8.221322e-002f, 7.232418e-002f, 6.057111e-002f, 4.794695e-002f, 3.544079e-002f, 2.392656e-002f, 1.407404e-002f, 6.293470e-003f, 7.195035e-004f, -2.766156e-003f, -4.479895e-003f, -4.860297e-003f, -4.384841e-003f, -3.493032e-003f, -2.527634e-003f, -1.701677e-003f, -1.093916e-003f, -6.701787e-004f, }
  };
  // fir1(filter_length,1250/r_nyquist(r));
  private static final float[][] corr_diff_filter_x1 = {
    { 2.492915e-003f, 3.578256e-002f, 1.601514e-001f, 3.015732e-001f, 3.015732e-001f, 1.601514e-001f, 3.578256e-002f, 2.492915e-003f, },
    { 1.355544e-003f, 1.575201e-002f, 7.177984e-002f, 1.668193e-001f, 2.442933e-001f, 2.442933e-001f, 1.668193e-001f, 7.177984e-002f, 1.575201e-002f, 1.355544e-003f, },
    { 2.294260e-003f, 2.406348e-002f, 1.064207e-001f, 2.253187e-001f, 2.838057e-001f, 2.253187e-001f, 1.064207e-001f, 2.406348e-002f, 2.294260e-003f, },
    { 4.119034e-004f, 2.581522e-003f, 8.710373e-003f, 2.169081e-002f, 4.252463e-002f, 6.939690e-002f, 9.778142e-002f, 1.216323e-001f, 1.352701e-001f, 1.352701e-001f, 1.216323e-001f, 9.778142e-002f, 6.939690e-002f, 4.252463e-002f, 2.169081e-002f, 8.710373e-003f, 2.581522e-003f, 4.119034e-004f, },
    { 1.044831e-004f, 1.648867e-003f, 5.677246e-003f, 1.428819e-002f, 2.867647e-002f, 4.847160e-002f, 7.152700e-002f, 9.427366e-002f, 1.125647e-001f, 1.227677e-001f, 1.227677e-001f, 1.125647e-001f, 9.427366e-002f, 7.152700e-002f, 4.847160e-002f, 2.867647e-002f, 1.428819e-002f, 5.677246e-003f, 1.648867e-003f, 1.044831e-004f, },
    { 4.315586e-005f, 4.044004e-004f, 9.935020e-004f, 2.010472e-003f, 3.650564e-003f, 6.080898e-003f, 9.418245e-003f, 1.371039e-002f, 1.892321e-002f, 2.493511e-002f, 3.153971e-002f, 3.845683e-002f, 4.535120e-002f, 5.185704e-002f, 5.760668e-002f, 6.226030e-002f, 6.553408e-002f, 6.722421e-002f, 6.722421e-002f, 6.553408e-002f, 6.226030e-002f, 5.760668e-002f, 5.185704e-002f, 4.535120e-002f, 3.845683e-002f, 3.153971e-002f, 2.493511e-002f, 1.892321e-002f, 1.371039e-002f, 9.418245e-003f, 6.080898e-003f, 3.650564e-003f, 2.010472e-003f, 9.935020e-004f, 4.044004e-004f, 4.315586e-005f, },
    { -7.527083e-005f, 1.985553e-004f, 6.082568e-004f, 1.285651e-003f, 2.364874e-003f, 3.969560e-003f, 6.199999e-003f, 9.121416e-003f, 1.275445e-002f, 1.706875e-002f, 2.198035e-002f, 2.735327e-002f, 3.300529e-002f, 3.871770e-002f, 4.424821e-002f, 4.934628e-002f, 5.376957e-002f, 5.730026e-002f, 5.976008e-002f, 6.102273e-002f, 6.102273e-002f, 5.976008e-002f, 5.730026e-002f, 5.376957e-002f, 4.934628e-002f, 4.424821e-002f, 3.871770e-002f, 3.300529e-002f, 2.735327e-002f, 2.198035e-002f, 1.706875e-002f, 1.275445e-002f, 9.121416e-003f, 6.199999e-003f, 3.969560e-003f, 2.364874e-003f, 1.285651e-003f, 6.082568e-004f, 1.985553e-004f, -7.527083e-005f, }
  };

  // filters that are 4 times longer than the bits-per-sample
  private static final float[][] time_domain_filter_xxx = {
    { -1.017892e-002f, -2.392462e-003f, 1.697165e-002f, 7.727152e-003f, -2.199618e-002f, -1.646221e-002f, 2.091247e-002f, 1.690428e-002f, -3.150775e-002f, -2.460631e-002f, 5.749648e-002f, 7.511379e-002f, -4.573396e-002f, -1.416559e-001f, -4.167783e-002f, 1.360032e-001f, 1.360032e-001f, -4.167783e-002f, -1.416559e-001f, -4.573396e-002f, 7.511379e-002f, 5.749648e-002f, -2.460631e-002f, -3.150775e-002f, 1.690428e-002f, 2.091247e-002f, -1.646221e-002f, -2.199618e-002f, 7.727152e-003f, 1.697165e-002f, -2.392462e-003f, -1.017892e-002f, },
    { -7.527588e-003f, -5.992088e-003f, 6.759312e-003f, 1.470919e-002f, 3.925369e-003f, -1.579521e-002f, -1.901689e-002f, 1.940622e-003f, 2.147329e-002f, 1.033158e-002f, -2.185309e-002f, -2.990864e-002f, 1.076817e-002f, 6.162560e-002f, 5.473580e-002f, -2.447855e-002f, -1.038836e-001f, -9.323900e-002f, 1.297972e-002f, 1.176225e-001f, 1.176225e-001f, 1.297972e-002f, -9.323900e-002f, -1.038836e-001f, -2.447855e-002f, 5.473580e-002f, 6.162560e-002f, 1.076817e-002f, -2.990864e-002f, -2.185309e-002f, 1.033158e-002f, 2.147329e-002f, 1.940622e-003f, -1.901689e-002f, -1.579521e-002f, 3.925369e-003f, 1.470919e-002f, 6.759312e-003f, -5.992088e-003f, -7.527588e-003f, },
    { -9.208364e-003f, -1.026661e-004f, 1.451246e-002f, 9.854309e-003f, -1.330607e-002f, -2.203440e-002f, 1.058497e-003f, 2.379095e-002f, 6.730599e-003f, -3.006230e-002f, -2.332162e-002f, 3.800499e-002f, 7.462702e-002f, 1.433031e-002f, -9.318806e-002f, -1.154643e-001f, -4.370331e-003f, 1.253313e-001f, 1.253313e-001f, -4.370331e-003f, -1.154643e-001f, -9.318806e-002f, 1.433031e-002f, 7.462702e-002f, 3.800499e-002f, -2.332162e-002f, -3.006230e-002f, 6.730599e-003f, 2.379095e-002f, 1.058497e-003f, -2.203440e-002f, -1.330607e-002f, 9.854309e-003f, 1.451246e-002f, -1.026661e-004f, -9.208364e-003f, },
    { -4.321078e-003f, -4.227200e-003f, -1.851028e-003f, 2.074214e-003f, 5.949560e-003f, 7.930708e-003f, 6.753111e-003f, 2.403573e-003f, -3.694815e-003f, -9.134324e-003f, -1.148547e-002f, -9.394998e-003f, -3.334375e-003f, 4.385682e-003f, 1.043318e-002f, 1.183985e-002f, 7.401191e-003f, -1.533047e-003f, -1.130675e-002f, -1.726568e-002f, -1.568734e-002f, -5.573205e-003f, 1.048321e-002f, 2.683448e-002f, 3.666675e-002f, 3.461290e-002f, 1.910723e-002f, -6.491716e-003f, -3.457632e-002f, -5.566362e-002f, -6.169457e-002f, -4.907342e-002f, -2.028789e-002f, 1.657297e-002f, 5.032665e-002f, 7.039557e-002f, 7.039557e-002f, 5.032665e-002f, 1.657297e-002f, -2.028789e-002f, -4.907342e-002f, -6.169457e-002f, -5.566362e-002f, -3.457632e-002f, -6.491716e-003f, 1.910723e-002f, 3.461290e-002f, 3.666675e-002f, 2.683448e-002f, 1.048321e-002f, -5.573205e-003f, -1.568734e-002f, -1.726568e-002f, -1.130675e-002f, -1.533047e-003f, 7.401191e-003f, 1.183985e-002f, 1.043318e-002f, 4.385682e-003f, -3.334375e-003f, -9.394998e-003f, -1.148547e-002f, -9.134324e-003f, -3.694815e-003f, 2.403573e-003f, 6.753111e-003f, 7.930708e-003f, 5.949560e-003f, 2.074214e-003f, -1.851028e-003f, -4.227200e-003f, -4.321078e-003f, },
    { -2.918426e-003f, -4.204358e-003f, -3.852348e-003f, -1.732497e-003f, 1.590087e-003f, 4.981858e-003f, 7.109914e-003f, 6.938233e-003f, 4.171528e-003f, -5.336874e-004f, -5.701261e-003f, -9.500360e-003f, -1.040242e-002f, -7.799155e-003f, -2.339804e-003f, 4.173663e-003f, 9.343675e-003f, 1.102624e-002f, 8.183890e-003f, 1.421219e-003f, -7.034236e-003f, -1.396268e-002f, -1.623150e-002f, -1.197918e-002f, -1.485381e-003f, 1.262128e-002f, 2.596490e-002f, 3.370942e-002f, 3.215604e-002f, 2.013424e-002f, -3.037613e-004f, -2.418000e-002f, -4.486410e-002f, -5.598347e-002f, -5.339960e-002f, -3.662496e-002f, -9.202574e-003f, 2.212024e-002f, 4.921641e-002f, 6.487415e-002f, 6.487415e-002f, 4.921641e-002f, 2.212024e-002f, -9.202574e-003f, -3.662496e-002f, -5.339960e-002f, -5.598347e-002f, -4.486410e-002f, -2.418000e-002f, -3.037613e-004f, 2.013424e-002f, 3.215604e-002f, 3.370942e-002f, 2.596490e-002f, 1.262128e-002f, -1.485381e-003f, -1.197918e-002f, -1.623150e-002f, -1.396268e-002f, -7.034236e-003f, 1.421219e-003f, 8.183890e-003f, 1.102624e-002f, 9.343675e-003f, 4.173663e-003f, -2.339804e-003f, -7.799155e-003f, -1.040242e-002f, -9.500360e-003f, -5.701261e-003f, -5.336874e-004f, 4.171528e-003f, 6.938233e-003f, 7.109914e-003f, 4.981858e-003f, 1.590087e-003f, -1.732497e-003f, -3.852348e-003f, -4.204358e-003f, -2.918426e-003f, },
    { -1.999567e-003f, -2.251715e-003f, -2.229956e-003f, -1.912810e-003f, -1.312464e-003f, -4.758688e-004f, 5.181918e-004f, 1.565982e-003f, 2.549104e-003f, 3.347226e-003f, 3.851900e-003f, 3.979961e-003f, 3.684890e-003f, 2.964715e-003f, 1.865303e-003f, 4.783690e-004f, -1.065899e-003f, -2.611088e-003f, -3.990583e-003f, -5.045762e-003f, -5.644419e-003f, -5.697331e-003f, -5.170966e-003f, -4.094665e-003f, -2.561133e-003f, -7.198013e-004f, 1.236638e-003f, 3.091406e-003f, 4.626713e-003f, 5.648389e-003f, 6.009390e-003f, 5.629515e-003f, 4.508885e-003f, 2.733330e-003f, 4.705918e-004f, -2.042799e-003f, -4.523098e-003f, -6.667526e-003f, -8.186404e-003f, -8.835994e-003f, -8.448562e-003f, -6.956289e-003f, -4.406099e-003f, -9.633339e-004f, 3.096788e-003f, 7.409718e-003f, 1.155268e-002f, 1.508372e-002f, 1.758505e-002f, 1.870670e-002f, 1.820575e-002f, 1.597735e-002f, 1.207373e-002f, 6.708846e-003f, 2.476490e-004f, -6.819842e-003f, -1.391761e-002f, -2.043268e-002f, -2.576976e-002f, -2.940642e-002f, -3.094363e-002f, -3.014661e-002f, -2.697197e-002f, -2.157807e-002f, -1.431735e-002f, -5.710704e-003f, 3.593769e-003f, 1.287446e-002f, 2.139741e-002f, 2.847947e-002f, 3.354775e-002f, 3.618976e-002f, 3.618976e-002f, 3.354775e-002f, 2.847947e-002f, 2.139741e-002f, 1.287446e-002f, 3.593769e-003f, -5.710704e-003f, -1.431735e-002f, -2.157807e-002f, -2.697197e-002f, -3.014661e-002f, -3.094363e-002f, -2.940642e-002f, -2.576976e-002f, -2.043268e-002f, -1.391761e-002f, -6.819842e-003f, 2.476490e-004f, 6.708846e-003f, 1.207373e-002f, 1.597735e-002f, 1.820575e-002f, 1.870670e-002f, 1.758505e-002f, 1.508372e-002f, 1.155268e-002f, 7.409718e-003f, 3.096788e-003f, -9.633339e-004f, -4.406099e-003f, -6.956289e-003f, -8.448562e-003f, -8.835994e-003f, -8.186404e-003f, -6.667526e-003f, -4.523098e-003f, -2.042799e-003f, 4.705918e-004f, 2.733330e-003f, 4.508885e-003f, 5.629515e-003f, 6.009390e-003f, 5.648389e-003f, 4.626713e-003f, 3.091406e-003f, 1.236638e-003f, -7.198013e-004f, -2.561133e-003f, -4.094665e-003f, -5.170966e-003f, -5.697331e-003f, -5.644419e-003f, -5.045762e-003f, -3.990583e-003f, -2.611088e-003f, -1.065899e-003f, 4.783690e-004f, 1.865303e-003f, 2.964715e-003f, 3.684890e-003f, 3.979961e-003f, 3.851900e-003f, 3.347226e-003f, 2.549104e-003f, 1.565982e-003f, 5.181918e-004f, -4.758688e-004f, -1.312464e-003f, -1.912810e-003f, -2.229956e-003f, -2.251715e-003f, -1.999567e-003f, },
    { -1.203204e-003f, -1.677825e-003f, -2.005440e-003f, -2.140786e-003f, -2.054700e-003f, -1.738138e-003f, -1.204469e-003f, -4.896900e-004f, 3.495868e-004f, 1.240303e-003f, 2.099012e-003f, 2.839347e-003f, 3.380235e-003f, 3.654119e-003f, 3.614369e-003f, 3.241115e-003f, 2.544851e-003f, 1.567310e-003f, 3.793934e-004f, -9.238425e-004f, -2.230804e-003f, -3.423011e-003f, -4.385961e-003f, -5.020230e-003f, -5.251769e-003f, -5.040356e-003f, -4.385299e-003f, -3.327690e-003f, -1.948816e-003f, -3.646494e-004f, 1.283261e-003f, 2.839838e-003f, 4.150495e-003f, 5.075897e-003f, 5.506135e-003f, 5.372927e-003f, 4.658627e-003f, 3.400992e-003f, 1.693048e-003f, -3.222058e-004f, -2.462062e-003f, -4.518662e-003f, -6.276749e-003f, -7.533177e-003f, -8.116507e-003f, -7.904900e-003f, -6.840639e-003f, -4.939761e-003f, -2.295713e-003f, 9.236403e-004f, 4.485723e-003f, 8.109174e-003f, 1.148492e-002f, 1.430084e-002f, 1.626807e-002f, 1.714677e-002f, 1.676911e-002f, 1.505752e-002f, 1.203630e-002f, 7.835391e-003f, 2.685763e-003f, -3.093705e-003f, -9.116985e-003f, -1.495793e-002f, -2.018161e-002f, -2.437750e-002f, -2.719204e-002f, -2.835777e-002f, -2.771668e-002f, -2.523587e-002f, -2.101392e-002f, -1.527727e-002f, -8.366833e-003f, -7.155283e-004f, 7.181604e-003f, 1.480248e-002f, 2.163564e-002f, 2.721751e-002f, 3.116658e-002f, 3.321155e-002f, 3.321155e-002f, 3.116658e-002f, 2.721751e-002f, 2.163564e-002f, 1.480248e-002f, 7.181604e-003f, -7.155283e-004f, -8.366833e-003f, -1.527727e-002f, -2.101392e-002f, -2.523587e-002f, -2.771668e-002f, -2.835777e-002f, -2.719204e-002f, -2.437750e-002f, -2.018161e-002f, -1.495793e-002f, -9.116985e-003f, -3.093705e-003f, 2.685763e-003f, 7.835391e-003f, 1.203630e-002f, 1.505752e-002f, 1.676911e-002f, 1.714677e-002f, 1.626807e-002f, 1.430084e-002f, 1.148492e-002f, 8.109174e-003f, 4.485723e-003f, 9.236403e-004f, -2.295713e-003f, -4.939761e-003f, -6.840639e-003f, -7.904900e-003f, -8.116507e-003f, -7.533177e-003f, -6.276749e-003f, -4.518662e-003f, -2.462062e-003f, -3.222058e-004f, 1.693048e-003f, 3.400992e-003f, 4.658627e-003f, 5.372927e-003f, 5.506135e-003f, 5.075897e-003f, 4.150495e-003f, 2.839838e-003f, 1.283261e-003f, -3.646494e-004f, -1.948816e-003f, -3.327690e-003f, -4.385299e-003f, -5.040356e-003f, -5.251769e-003f, -5.020230e-003f, -4.385961e-003f, -3.423011e-003f, -2.230804e-003f, -9.238425e-004f, 3.793934e-004f, 1.567310e-003f, 2.544851e-003f, 3.241115e-003f, 3.614369e-003f, 3.654119e-003f, 3.380235e-003f, 2.839347e-003f, 2.099012e-003f, 1.240303e-003f, 3.495868e-004f, -4.896900e-004f, -1.204469e-003f, -1.738138e-003f, -2.054700e-003f, -2.140786e-003f, -2.005440e-003f, -1.677825e-003f, -1.203204e-003f, }
  };
  private static final float[][] corr_diff_filter_xxx = {
    { -6.304691e-004f, -1.818568e-003f, -2.561942e-003f, -1.587494e-003f, 2.369513e-003f, 8.332497e-003f, 1.180361e-002f, 6.759297e-003f, -9.174512e-003f, -2.973091e-002f, -3.981645e-002f, -2.230165e-002f, 3.102797e-002f, 1.111435e-001f, 1.924554e-001f, 2.437302e-001f, 2.437302e-001f, 1.924554e-001f, 1.111435e-001f, 3.102797e-002f, -2.230165e-002f, -3.981645e-002f, -2.973091e-002f, -9.174512e-003f, 6.759297e-003f, 1.180361e-002f, 8.332497e-003f, 2.369513e-003f, -1.587494e-003f, -2.561942e-003f, -1.818568e-003f, -6.304691e-004f, },
    { -4.046374e-004f, -1.199761e-003f, -1.890849e-003f, -2.076543e-003f, -1.096110e-003f, 1.505622e-003f, 5.330573e-003f, 8.753080e-003f, 9.251377e-003f, 4.551586e-003f, -5.798659e-003f, -1.919960e-002f, -2.992233e-002f, -3.058886e-002f, -1.490081e-002f, 1.938229e-002f, 6.852266e-002f, 1.229704e-001f, 1.698441e-001f, 1.969665e-001f, 1.969665e-001f, 1.698441e-001f, 1.229704e-001f, 6.852266e-002f, 1.938229e-002f, -1.490081e-002f, -3.058886e-002f, -2.992233e-002f, -1.919960e-002f, -5.798659e-003f, 4.551586e-003f, 9.251377e-003f, 8.753080e-003f, 5.330573e-003f, 1.505622e-003f, -1.096110e-003f, -2.076543e-003f, -1.890849e-003f, -1.199761e-003f, -4.046374e-004f, },
    { -8.220119e-004f, -1.620798e-003f, -2.077875e-003f, -1.507786e-003f, 8.749990e-004f, 4.967786e-003f, 8.937823e-003f, 9.456198e-003f, 3.408210e-003f, -9.538261e-003f, -2.499943e-002f, -3.414151e-002f, -2.674668e-002f, 3.898932e-003f, 5.658318e-002f, 1.206920e-001f, 1.789611e-001f, 2.136742e-001f, 2.136742e-001f, 1.789611e-001f, 1.206920e-001f, 5.658318e-002f, 3.898932e-003f, -2.674668e-002f, -3.414151e-002f, -2.499943e-002f, -9.538261e-003f, 3.408210e-003f, 9.456198e-003f, 8.937823e-003f, 4.967786e-003f, 8.749990e-004f, -1.507786e-003f, -2.077875e-003f, -1.620798e-003f, -8.220119e-004f, },
    { -2.981248e-004f, -5.264109e-004f, -7.444341e-004f, -9.373140e-004f, -1.071893e-003f, -1.097563e-003f, -9.537972e-004f, -5.838805e-004f, 4.725428e-005f, 9.344779e-004f, 2.017401e-003f, 3.173017e-003f, 4.219454e-003f, 4.932689e-003f, 5.075866e-003f, 4.438516e-003f, 2.880713e-003f, 3.755560e-004f, -2.957361e-003f, -6.834448e-003f, -1.081192e-002f, -1.431361e-002f, -1.668226e-002f, -1.724990e-002f, -1.542008e-002f, -1.075175e-002f, -3.033942e-003f, 7.659911e-003f, 2.094660e-002f, 3.614254e-002f, 5.230930e-002f, 6.833175e-002f, 8.302139e-002f, 9.523307e-002f, 1.039821e-001f, 1.085471e-001f, 1.085471e-001f, 1.039821e-001f, 9.523307e-002f, 8.302139e-002f, 6.833175e-002f, 5.230930e-002f, 3.614254e-002f, 2.094660e-002f, 7.659911e-003f, -3.033942e-003f, -1.075175e-002f, -1.542008e-002f, -1.724990e-002f, -1.668226e-002f, -1.431361e-002f, -1.081192e-002f, -6.834448e-003f, -2.957361e-003f, 3.755560e-004f, 2.880713e-003f, 4.438516e-003f, 5.075866e-003f, 4.932689e-003f, 4.219454e-003f, 3.173017e-003f, 2.017401e-003f, 9.344779e-004f, 4.725428e-005f, -5.838805e-004f, -9.537972e-004f, -1.097563e-003f, -1.071893e-003f, -9.373140e-004f, -7.444341e-004f, -5.264109e-004f, -2.981248e-004f, },
    { -1.011125e-004f, -3.065340e-004f, -5.163660e-004f, -7.247702e-004f, -9.152863e-004f, -1.058882e-003f, -1.115264e-003f, -1.037835e-003f, -7.819902e-004f, -3.157511e-004f, 3.688993e-004f, 1.246003e-003f, 2.249083e-003f, 3.269968e-003f, 4.164339e-003f, 4.764458e-003f, 4.898509e-003f, 4.414910e-003f, 3.208931e-003f, 1.248295e-003f, -1.405934e-003f, -4.586672e-003f, -8.019223e-003f, -1.133254e-002f, -1.408366e-002f, -1.579399e-002f, -1.599461e-002f, -1.427629e-002f, -1.033899e-002f, -4.035334e-003f, 4.597366e-003f, 1.532086e-002f, 2.769843e-002f, 4.111713e-002f, 5.482850e-002f, 6.800481e-002f, 7.980553e-002f, 8.944795e-002f, 9.627480e-002f, 9.981227e-002f, 9.981227e-002f, 9.627480e-002f, 8.944795e-002f, 7.980553e-002f, 6.800481e-002f, 5.482850e-002f, 4.111713e-002f, 2.769843e-002f, 1.532086e-002f, 4.597366e-003f, -4.035334e-003f, -1.033899e-002f, -1.427629e-002f, -1.599461e-002f, -1.579399e-002f, -1.408366e-002f, -1.133254e-002f, -8.019223e-003f, -4.586672e-003f, -1.405934e-003f, 1.248295e-003f, 3.208931e-003f, 4.414910e-003f, 4.898509e-003f, 4.764458e-003f, 4.164339e-003f, 3.269968e-003f, 2.249083e-003f, 1.246003e-003f, 3.688993e-004f, -3.157511e-004f, -7.819902e-004f, -1.037835e-003f, -1.115264e-003f, -1.058882e-003f, -9.152863e-004f, -7.247702e-004f, -5.163660e-004f, -3.065340e-004f, -1.011125e-004f, },
    { -1.197261e-004f, -1.786836e-004f, -2.372301e-004f, -2.952118e-004f, -3.520734e-004f, -4.067501e-004f, -4.575942e-004f, -5.023455e-004f, -5.381511e-004f, -5.616392e-004f, -5.690469e-004f, -5.563995e-004f, -5.197374e-004f, -4.553792e-004f, -3.602120e-004f, -2.319936e-004f, -6.965116e-005f, 1.264406e-004f, 3.542190e-004f, 6.097481e-004f, 8.871037e-004f, 1.178343e-003f, 1.473569e-003f, 1.761096e-003f, 2.027723e-003f, 2.259109e-003f, 2.440246e-003f, 2.556014e-003f, 2.591818e-003f, 2.534260e-003f, 2.371852e-003f, 2.095717e-003f, 1.700270e-003f, 1.183834e-003f, 5.491781e-004f, -1.960724e-004f, -1.039155e-003f, -1.962059e-003f, -2.941584e-003f, -3.949596e-003f, -4.953475e-003f, -5.916746e-003f, -6.799900e-003f, -7.561374e-003f, -8.158675e-003f, -8.549607e-003f, -8.693583e-003f, -8.552960e-003f, -8.094376e-003f, -7.290031e-003f, -6.118866e-003f, -4.567609e-003f, -2.631636e-003f, -3.156163e-004f, 2.366088e-003f, 5.389289e-003f, 8.720126e-003f, 1.231550e-002f, 1.612380e-002f, 2.008590e-002f, 2.413639e-002f, 2.820504e-002f, 3.221843e-002f, 3.610173e-002f, 3.978056e-002f, 4.318282e-002f, 4.624061e-002f, 4.889196e-002f, 5.108246e-002f, 5.276673e-002f, 5.390962e-002f, 5.448713e-002f, 5.448713e-002f, 5.390962e-002f, 5.276673e-002f, 5.108246e-002f, 4.889196e-002f, 4.624061e-002f, 4.318282e-002f, 3.978056e-002f, 3.610173e-002f, 3.221843e-002f, 2.820504e-002f, 2.413639e-002f, 2.008590e-002f, 1.612380e-002f, 1.231550e-002f, 8.720126e-003f, 5.389289e-003f, 2.366088e-003f, -3.156163e-004f, -2.631636e-003f, -4.567609e-003f, -6.118866e-003f, -7.290031e-003f, -8.094376e-003f, -8.552960e-003f, -8.693583e-003f, -8.549607e-003f, -8.158675e-003f, -7.561374e-003f, -6.799900e-003f, -5.916746e-003f, -4.953475e-003f, -3.949596e-003f, -2.941584e-003f, -1.962059e-003f, -1.039155e-003f, -1.960724e-004f, 5.491781e-004f, 1.183834e-003f, 1.700270e-003f, 2.095717e-003f, 2.371852e-003f, 2.534260e-003f, 2.591818e-003f, 2.556014e-003f, 2.440246e-003f, 2.259109e-003f, 2.027723e-003f, 1.761096e-003f, 1.473569e-003f, 1.178343e-003f, 8.871037e-004f, 6.097481e-004f, 3.542190e-004f, 1.264406e-004f, -6.965116e-005f, -2.319936e-004f, -3.602120e-004f, -4.553792e-004f, -5.197374e-004f, -5.563995e-004f, -5.690469e-004f, -5.616392e-004f, -5.381511e-004f, -5.023455e-004f, -4.575942e-004f, -4.067501e-004f, -3.520734e-004f, -2.952118e-004f, -2.372301e-004f, -1.786836e-004f, -1.197261e-004f, },
    { -2.519612e-005f, -7.626377e-005f, -1.283280e-004f, -1.814113e-004f, -2.353540e-004f, -2.897360e-004f, -3.438103e-004f, -3.964534e-004f, -4.461368e-004f, -4.909241e-004f, -5.284956e-004f, -5.562015e-004f, -5.711452e-004f, -5.702934e-004f, -5.506123e-004f, -5.092236e-004f, -4.435771e-004f, -3.516305e-004f, -2.320321e-004f, -8.429565e-005f, 9.104032e-005f, 2.922768e-004f, 5.164514e-004f, 7.592751e-004f, 1.015115e-003f, 1.277033e-003f, 1.536869e-003f, 1.785399e-003f, 2.012534e-003f, 2.207578e-003f, 2.359547e-003f, 2.457514e-003f, 2.491000e-003f, 2.450389e-003f, 2.327349e-003f, 2.115254e-003f, 1.809595e-003f, 1.408352e-003f, 9.123291e-004f, 3.254212e-004f, -3.451811e-004f, -1.088877e-003f, -1.891634e-003f, -2.736058e-003f, -3.601582e-003f, -4.464746e-003f, -5.299588e-003f, -6.078130e-003f, -6.770957e-003f, -7.347871e-003f, -7.778608e-003f, -8.033605e-003f, -8.084792e-003f, -7.906389e-003f, -7.475694e-003f, -6.773828e-003f, -5.786420e-003f, -4.504216e-003f, -2.923585e-003f, -1.046905e-003f, 1.117177e-003f, 3.553638e-003f, 6.241115e-003f, 9.152104e-003f, 1.225331e-002f, 1.550616e-002f, 1.886742e-002f, 2.229002e-002f, 2.572388e-002f, 2.911695e-002f, 3.241622e-002f, 3.556886e-002f, 3.852326e-002f, 4.123024e-002f, 4.364402e-002f, 4.572330e-002f, 4.743213e-002f, 4.874072e-002f, 4.962614e-002f, 5.007279e-002f, 5.007279e-002f, 4.962614e-002f, 4.874072e-002f, 4.743213e-002f, 4.572330e-002f, 4.364402e-002f, 4.123024e-002f, 3.852326e-002f, 3.556886e-002f, 3.241622e-002f, 2.911695e-002f, 2.572388e-002f, 2.229002e-002f, 1.886742e-002f, 1.550616e-002f, 1.225331e-002f, 9.152104e-003f, 6.241115e-003f, 3.553638e-003f, 1.117177e-003f, -1.046905e-003f, -2.923585e-003f, -4.504216e-003f, -5.786420e-003f, -6.773828e-003f, -7.475694e-003f, -7.906389e-003f, -8.084792e-003f, -8.033605e-003f, -7.778608e-003f, -7.347871e-003f, -6.770957e-003f, -6.078130e-003f, -5.299588e-003f, -4.464746e-003f, -3.601582e-003f, -2.736058e-003f, -1.891634e-003f, -1.088877e-003f, -3.451811e-004f, 3.254212e-004f, 9.123291e-004f, 1.408352e-003f, 1.809595e-003f, 2.115254e-003f, 2.327349e-003f, 2.450389e-003f, 2.491000e-003f, 2.457514e-003f, 2.359547e-003f, 2.207578e-003f, 2.012534e-003f, 1.785399e-003f, 1.536869e-003f, 1.277033e-003f, 1.015115e-003f, 7.592751e-004f, 5.164514e-004f, 2.922768e-004f, 9.104032e-005f, -8.429565e-005f, -2.320321e-004f, -3.516305e-004f, -4.435771e-004f, -5.092236e-004f, -5.506123e-004f, -5.702934e-004f, -5.711452e-004f, -5.562015e-004f, -5.284956e-004f, -4.909241e-004f, -4.461368e-004f, -3.964534e-004f, -3.438103e-004f, -2.897360e-004f, -2.353540e-004f, -1.814113e-004f, -1.283280e-004f, -7.626377e-005f, -2.519612e-005f, }
  };

  private static final float[][] time_domain_filter = {
    { 4.959380e-005f, 5.319873e-003f, 2.893326e-003f, -6.936664e-003f, -2.234023e-003f, 1.081975e-002f, -2.688869e-003f, -2.442595e-002f, -1.228120e-003f, 3.082726e-002f, -3.300164e-003f, -3.915167e-002f, 2.916328e-002f, 9.269023e-002f, -1.915007e-002f, -1.648895e-001f, -6.863031e-002f, 1.623141e-001f, 1.623141e-001f, -6.863031e-002f, -1.648895e-001f, -1.915007e-002f, 9.269023e-002f, 2.916328e-002f, -3.915167e-002f, -3.300164e-003f, 3.082726e-002f, -1.228120e-003f, -2.442595e-002f, -2.688869e-003f, 1.081975e-002f, -2.234023e-003f, -6.936664e-003f, 2.893326e-003f, 5.319873e-003f, 4.959380e-005f, },
    { -1.770981e-003f, 5.578543e-004f, 4.453762e-003f, 3.248468e-003f, -3.651099e-003f, -6.162672e-003f, 2.164718e-003f, 9.939817e-003f, 1.309157e-003f, -1.630817e-002f, -1.570593e-002f, 9.313801e-003f, 2.500023e-002f, 2.249884e-003f, -3.064951e-002f, -1.559888e-002f, 4.636809e-002f, 7.233762e-002f, -4.444594e-004f, -1.104007e-001f, -1.226306e-001f, 3.455560e-003f, 1.434371e-001f, 1.434371e-001f, 3.455560e-003f, -1.226306e-001f, -1.104007e-001f, -4.444594e-004f, 7.233762e-002f, 4.636809e-002f, -1.559888e-002f, -3.064951e-002f, 2.249884e-003f, 2.500023e-002f, 9.313801e-003f, -1.570593e-002f, -1.630817e-002f, 1.309157e-003f, 9.939817e-003f, 2.164718e-003f, -6.162672e-003f, -3.651099e-003f, 3.248468e-003f, 4.453762e-003f, 5.578543e-004f, -1.770981e-003f, },
    { 8.404552e-004f, 4.780269e-003f, 3.571689e-003f, -4.034292e-003f, -5.731477e-003f, 4.275072e-003f, 8.368463e-003f, -7.742271e-003f, -2.158670e-002f, -3.524517e-003f, 2.470331e-002f, 1.264578e-002f, -2.761578e-002f, -1.951381e-002f, 5.073275e-002f, 7.668835e-002f, -1.996824e-002f, -1.367232e-001f, -1.011481e-001f, 7.436337e-002f, 1.768607e-001f, 7.436337e-002f, -1.011481e-001f, -1.367232e-001f, -1.996824e-002f, 7.668835e-002f, 5.073275e-002f, -1.951381e-002f, -2.761578e-002f, 1.264578e-002f, 2.470331e-002f, -3.524517e-003f, -2.158670e-002f, -7.742271e-003f, 8.368463e-003f, 4.275072e-003f, -5.731477e-003f, -4.034292e-003f, 3.571689e-003f, 4.780269e-003f, 8.404552e-004f, },
    { -9.584167e-004f, -1.189653e-003f, -7.782507e-004f, 2.997938e-004f, 1.659615e-003f, 2.618996e-003f, 2.527796e-003f, 1.167827e-003f, -1.003813e-003f, -2.953541e-003f, -3.534709e-003f, -2.126232e-003f, 8.876260e-004f, 4.109014e-003f, 5.695287e-003f, 4.301445e-003f, -5.953817e-005f, -5.736420e-003f, -1.000792e-002f, -1.034771e-002f, -5.823640e-003f, 2.104583e-003f, 9.927816e-003f, 1.358744e-002f, 1.053530e-002f, 1.360124e-003f, -9.947433e-003f, -1.745890e-002f, -1.603510e-002f, -4.133589e-003f, 1.470408e-002f, 3.263148e-002f, 4.050573e-002f, 3.200048e-002f, 7.026732e-003f, -2.722325e-002f, -5.837337e-002f, -7.350189e-002f, -6.451264e-002f, -3.195436e-002f, 1.447544e-002f, 5.916588e-002f, 8.639695e-002f, 8.639695e-002f, 5.916588e-002f, 1.447544e-002f, -3.195436e-002f, -6.451264e-002f, -7.350189e-002f, -5.837337e-002f, -2.722325e-002f, 7.026732e-003f, 3.200048e-002f, 4.050573e-002f, 3.263148e-002f, 1.470408e-002f, -4.133589e-003f, -1.603510e-002f, -1.745890e-002f, -9.947433e-003f, 1.360124e-003f, 1.053530e-002f, 1.358744e-002f, 9.927816e-003f, 2.104583e-003f, -5.823640e-003f, -1.034771e-002f, -1.000792e-002f, -5.736420e-003f, -5.953817e-005f, 4.301445e-003f, 5.695287e-003f, 4.109014e-003f, 8.876260e-004f, -2.126232e-003f, -3.534709e-003f, -2.953541e-003f, -1.003813e-003f, 1.167827e-003f, 2.527796e-003f, 2.618996e-003f, 1.659615e-003f, 2.997938e-004f, -7.782507e-004f, -1.189653e-003f, -9.584167e-004f, },
    { -5.847319e-004f, -1.074868e-003f, -1.291514e-003f, -1.001864e-003f, -1.546426e-004f, 1.036770e-003f, 2.127233e-003f, 2.601064e-003f, 2.109747e-003f, 6.830833e-004f, -1.198613e-003f, -2.737937e-003f, -3.137612e-003f, -1.984566e-003f, 4.720280e-004f, 3.303719e-003f, 5.205505e-003f, 5.035227e-003f, 2.379310e-003f, -2.115097e-003f, -6.837493e-003f, -9.770633e-003f, -9.329291e-003f, -5.145846e-003f, 1.562171e-003f, 8.275775e-003f, 1.208595e-002f, 1.092529e-002f, 4.624028e-003f, -4.701408e-003f, -1.319913e-002f, -1.667550e-002f, -1.235989e-002f, -3.458491e-004f, 1.594279e-002f, 3.059108e-002f, 3.717205e-002f, 3.121689e-002f, 1.225633e-002f, -1.541620e-002f, -4.369394e-002f, -6.313119e-002f, -6.615618e-002f, -4.989580e-002f, -1.755303e-002f, 2.225057e-002f, 5.803989e-002f, 7.913382e-002f, 7.913382e-002f, 5.803989e-002f, 2.225057e-002f, -1.755303e-002f, -4.989580e-002f, -6.615618e-002f, -6.313119e-002f, -4.369394e-002f, -1.541620e-002f, 1.225633e-002f, 3.121689e-002f, 3.717205e-002f, 3.059108e-002f, 1.594279e-002f, -3.458491e-004f, -1.235989e-002f, -1.667550e-002f, -1.319913e-002f, -4.701408e-003f, 4.624028e-003f, 1.092529e-002f, 1.208595e-002f, 8.275775e-003f, 1.562171e-003f, -5.145846e-003f, -9.329291e-003f, -9.770633e-003f, -6.837493e-003f, -2.115097e-003f, 2.379310e-003f, 5.035227e-003f, 5.205505e-003f, 3.303719e-003f, 4.720280e-004f, -1.984566e-003f, -3.137612e-003f, -2.737937e-003f, -1.198613e-003f, 6.830833e-004f, 2.109747e-003f, 2.601064e-003f, 2.127233e-003f, 1.036770e-003f, -1.546426e-004f, -1.001864e-003f, -1.291514e-003f, -1.074868e-003f, -5.847319e-004f, },
    { -2.660550e-004f, -4.217618e-004f, -5.615726e-004f, -6.600045e-004f, -6.930207e-004f, -6.420347e-004f, -4.976665e-004f, -2.626276e-004f, 4.683031e-005f, 4.013181e-004f, 7.607417e-004f, 1.078656e-003f, 1.308129e-003f, 1.408426e-003f, 1.351620e-003f, 1.128155e-003f, 7.504133e-004f, 2.535449e-004f, -3.068714e-004f, -8.603528e-004f, -1.329776e-003f, -1.641496e-003f, -1.736075e-003f, -1.578161e-003f, -1.164034e-003f, -5.255165e-004f, 2.706697e-004f, 1.128470e-003f, 1.932693e-003f, 2.562885e-003f, 2.909308e-003f, 2.889034e-003f, 2.459944e-003f, 1.630539e-003f, 4.638065e-004f, -9.258903e-004f, -2.383145e-003f, -3.728295e-003f, -4.778977e-003f, -5.373991e-003f, -5.396465e-003f, -4.793173e-003f, -3.587122e-003f, -1.881154e-003f, 1.486655e-004f, 2.269839e-003f, 4.219059e-003f, 5.734020e-003f, 6.587775e-003f, 6.621365e-003f, 5.770358e-003f, 4.081372e-003f, 1.715653e-003f, -1.061778e-003f, -3.907166e-003f, -6.435188e-003f, -8.264501e-003f, -9.066591e-003f, -8.612074e-003f, -6.808518e-003f, -3.724466e-003f, 4.042950e-004f, 5.188279e-003f, 1.011744e-002f, 1.461132e-002f, 1.808132e-002f, 1.999867e-002f, 1.996031e-002f, 1.774504e-002f, 1.335267e-002f, 7.020762e-003f, -7.842241e-004f, -9.401845e-003f, -1.803601e-002f, -2.583141e-002f, -3.196040e-002f, -3.571117e-002f, -3.656759e-002f, -3.427175e-002f, -2.886164e-002f, -2.067921e-002f, -1.034699e-002f, 1.285142e-003f, 1.321796e-002f, 2.439810e-002f, 3.382059e-002f, 4.062804e-002f, 4.419612e-002f, 4.419612e-002f, 4.062804e-002f, 3.382059e-002f, 2.439810e-002f, 1.321796e-002f, 1.285142e-003f, -1.034699e-002f, -2.067921e-002f, -2.886164e-002f, -3.427175e-002f, -3.656759e-002f, -3.571117e-002f, -3.196040e-002f, -2.583141e-002f, -1.803601e-002f, -9.401845e-003f, -7.842241e-004f, 7.020762e-003f, 1.335267e-002f, 1.774504e-002f, 1.996031e-002f, 1.999867e-002f, 1.808132e-002f, 1.461132e-002f, 1.011744e-002f, 5.188279e-003f, 4.042950e-004f, -3.724466e-003f, -6.808518e-003f, -8.612074e-003f, -9.066591e-003f, -8.264501e-003f, -6.435188e-003f, -3.907166e-003f, -1.061778e-003f, 1.715653e-003f, 4.081372e-003f, 5.770358e-003f, 6.621365e-003f, 6.587775e-003f, 5.734020e-003f, 4.219059e-003f, 2.269839e-003f, 1.486655e-004f, -1.881154e-003f, -3.587122e-003f, -4.793173e-003f, -5.396465e-003f, -5.373991e-003f, -4.778977e-003f, -3.728295e-003f, -2.383145e-003f, -9.258903e-004f, 4.638065e-004f, 1.630539e-003f, 2.459944e-003f, 2.889034e-003f, 2.909308e-003f, 2.562885e-003f, 1.932693e-003f, 1.128470e-003f, 2.706697e-004f, -5.255165e-004f, -1.164034e-003f, -1.578161e-003f, -1.736075e-003f, -1.641496e-003f, -1.329776e-003f, -8.603528e-004f, -3.068714e-004f, 2.535449e-004f, 7.504133e-004f, 1.128155e-003f, 1.351620e-003f, 1.408426e-003f, 1.308129e-003f, 1.078656e-003f, 7.607417e-004f, 4.013181e-004f, 4.683031e-005f, -2.626276e-004f, -4.976665e-004f, -6.420347e-004f, -6.930207e-004f, -6.600045e-004f, -5.615726e-004f, -4.217618e-004f, -2.660550e-004f, },
    { -3.621270e-005f, -1.440807e-004f, -2.699467e-004f, -4.009667e-004f, -5.210394e-004f, -6.124228e-004f, -6.578149e-004f, -6.426782e-004f, -5.575336e-004f, -3.999163e-004f, -1.756966e-004f, 1.004844e-004f, 4.058289e-004f, 7.110939e-004f, 9.833137e-004f, 1.189309e-003f, 1.299635e-003f, 1.292529e-003f, 1.157366e-003f, 8.971548e-004f, 5.296585e-004f, 8.686122e-005f, -3.873201e-004f, -8.409878e-004f, -1.219568e-003f, -1.471969e-003f, -1.556940e-003f, -1.448895e-003f, -1.142463e-003f, -6.551062e-004f, -2.730810e-005f, 6.798950e-004f, 1.390013e-003f, 2.018465e-003f, 2.481556e-003f, 2.706171e-003f, 2.639129e-003f, 2.255101e-003f, 1.562036e-003f, 6.032979e-004f, -5.440358e-004f, -1.774829e-003f, -2.965173e-003f, -3.984567e-003f, -4.709834e-003f, -5.039362e-003f, -4.906098e-003f, -4.287733e-003f, -3.212736e-003f, -1.761238e-003f, -6.027875e-005f, 1.726497e-003f, 3.413971e-003f, 4.814200e-003f, 5.756825e-003f, 6.109105e-003f, 5.793388e-003f, 4.799926e-003f, 3.193292e-003f, 1.111258e-003f, -1.244309e-003f, -3.624129e-003f, -5.754535e-003f, -7.364857e-003f, -8.216578e-003f, -8.131338e-003f, -7.014760e-003f, -4.873363e-003f, -1.822324e-003f, 1.917307e-003f, 6.032360e-003f, 1.014158e-002f, 1.382818e-002f, 1.667818e-002f, 1.832111e-002f, 1.846912e-002f, 1.695068e-002f, 1.373520e-002f, 8.945686e-003f, 2.857649e-003f, -4.116342e-003f, -1.145575e-002f, -1.857264e-002f, -2.486041e-002f, -2.974656e-002f, -3.274466e-002f, -3.350083e-002f, -3.183007e-002f, -2.773904e-002f, -2.143251e-002f, -1.330276e-002f, -3.902161e-003f, 6.098803e-003f, 1.596468e-002f, 2.495485e-002f, 3.238466e-002f, 3.768268e-002f, 4.043877e-002f, 4.043877e-002f, 3.768268e-002f, 3.238466e-002f, 2.495485e-002f, 1.596468e-002f, 6.098803e-003f, -3.902161e-003f, -1.330276e-002f, -2.143251e-002f, -2.773904e-002f, -3.183007e-002f, -3.350083e-002f, -3.274466e-002f, -2.974656e-002f, -2.486041e-002f, -1.857264e-002f, -1.145575e-002f, -4.116342e-003f, 2.857649e-003f, 8.945686e-003f, 1.373520e-002f, 1.695068e-002f, 1.846912e-002f, 1.832111e-002f, 1.667818e-002f, 1.382818e-002f, 1.014158e-002f, 6.032360e-003f, 1.917307e-003f, -1.822324e-003f, -4.873363e-003f, -7.014760e-003f, -8.131338e-003f, -8.216578e-003f, -7.364857e-003f, -5.754535e-003f, -3.624129e-003f, -1.244309e-003f, 1.111258e-003f, 3.193292e-003f, 4.799926e-003f, 5.793388e-003f, 6.109105e-003f, 5.756825e-003f, 4.814200e-003f, 3.413971e-003f, 1.726497e-003f, -6.027875e-005f, -1.761238e-003f, -3.212736e-003f, -4.287733e-003f, -4.906098e-003f, -5.039362e-003f, -4.709834e-003f, -3.984567e-003f, -2.965173e-003f, -1.774829e-003f, -5.440358e-004f, 6.032979e-004f, 1.562036e-003f, 2.255101e-003f, 2.639129e-003f, 2.706171e-003f, 2.481556e-003f, 2.018465e-003f, 1.390013e-003f, 6.798950e-004f, -2.730810e-005f, -6.551062e-004f, -1.142463e-003f, -1.448895e-003f, -1.556940e-003f, -1.471969e-003f, -1.219568e-003f, -8.409878e-004f, -3.873201e-004f, 8.686122e-005f, 5.296585e-004f, 8.971548e-004f, 1.157366e-003f, 1.292529e-003f, 1.299635e-003f, 1.189309e-003f, 9.833137e-004f, 7.110939e-004f, 4.058289e-004f, 1.004844e-004f, -1.756966e-004f, -3.999163e-004f, -5.575336e-004f, -6.426782e-004f, -6.578149e-004f, -6.124228e-004f, -5.210394e-004f, -4.009667e-004f, -2.699467e-004f, -1.440807e-004f, -3.621270e-005f, }
  };
  private static final float[][] corr_diff_filter = {
    { 3.560173e-003f, 3.808372e-002f, 1.610319e-001f, 2.973243e-001f, 2.973243e-001f, 1.610319e-001f, 3.808372e-002f, 3.560173e-003f, },
    { 2.199047e-003f, 1.735971e-002f, 7.367287e-002f, 1.662386e-001f, 2.405298e-001f, 2.405298e-001f, 1.662386e-001f, 7.367287e-002f, 1.735971e-002f, 2.199047e-003f, },
    { 3.225875e-003f, 2.591391e-002f, 1.079899e-001f, 2.232384e-001f, 2.792639e-001f, 2.232384e-001f, 1.079899e-001f, 2.591391e-002f, 3.225875e-003f, },
    { 8.636339e-004f, 3.182517e-003f, 9.639032e-003f, 2.284951e-002f, 4.353592e-002f, 6.976907e-002f, 9.715855e-002f, 1.199990e-001f, 1.330028e-001f, 1.330028e-001f, 1.199990e-001f, 9.715855e-002f, 6.976907e-002f, 4.353592e-002f, 2.284951e-002f, 9.639032e-003f, 3.182517e-003f, 8.636339e-004f, },
    { 5.110546e-004f, 2.174060e-003f, 6.473724e-003f, 1.533688e-002f, 2.975306e-002f, 4.921456e-002f, 7.157931e-002f, 9.343798e-002f, 1.109054e-001f, 1.206140e-001f, 1.206140e-001f, 1.109054e-001f, 9.343798e-002f, 7.157931e-002f, 4.921456e-002f, 2.975306e-002f, 1.533688e-002f, 6.473724e-003f, 2.174060e-003f, 5.110546e-004f, },
    { 2.639688e-004f, 6.466073e-004f, 1.289839e-003f, 2.384937e-003f, 4.112716e-003f, 6.622334e-003f, 1.001174e-002f, 1.431186e-002f, 1.947623e-002f, 2.537743e-002f, 3.181093e-002f, 3.850630e-002f, 4.514497e-002f, 5.138316e-002f, 5.687791e-002f, 6.131400e-002f, 6.442924e-002f, 6.603583e-002f, 6.603583e-002f, 6.442924e-002f, 6.131400e-002f, 5.687791e-002f, 5.138316e-002f, 4.514497e-002f, 3.850630e-002f, 3.181093e-002f, 2.537743e-002f, 1.947623e-002f, 1.431186e-002f, 1.001174e-002f, 6.622334e-003f, 4.112716e-003f, 2.384937e-003f, 1.289839e-003f, 6.466073e-004f, 2.639688e-004f, },
    { 1.230588e-004f, 4.146753e-004f, 8.667268e-004f, 1.606401e-003f, 2.759319e-003f, 4.437769e-003f, 6.729266e-003f, 9.686389e-003f, 1.331883e-002f, 1.758836e-002f, 2.240733e-002f, 2.764087e-002f, 3.311284e-002f, 3.861510e-002f, 4.391962e-002f, 4.879247e-002f, 5.300873e-002f, 5.636712e-002f, 5.870346e-002f, 5.990168e-002f, 5.990168e-002f, 5.870346e-002f, 5.636712e-002f, 5.300873e-002f, 4.879247e-002f, 4.391962e-002f, 3.861510e-002f, 3.311284e-002f, 2.764087e-002f, 2.240733e-002f, 1.758836e-002f, 1.331883e-002f, 9.686389e-003f, 6.729266e-003f, 4.437769e-003f, 2.759319e-003f, 1.606401e-003f, 8.667268e-004f, 4.146753e-004f, 1.230588e-004f, }
  };
*/
  private float[] td_filter;
  private float[] cd_filter;
  
  private int rate_index;
  
	private int sample_rate, samples_per_bit;
	//private float[] u1, u2, x, f0_cos, f0_sin, f1_cos, f1_sin;
	private float[] u1, x;
	private float[] c0_real, c0_imag, c1_real, c1_imag;
	private float[] diff;
	//private float[] fdiff;
	private float previous_fdiff;
	private int f0_i=0, f1_i=0;
	private int last_transition;
	private int data, bitcount;
	
	private float phase_inc_f0, phase_inc_f1;
	private float phase_inc_symbol;
	
	private Packet packet; // received packet
	private PacketHandler handler;
	
	private static enum State {
		WAITING,
		JUST_SEEN_FLAG,
		DECODING
	};
	private State state = State.WAITING;
	
	//TransmitController transmit_controller;
	
	private int filter_index;
	
	public XXXAfsk1200(int sample_rate, int filter_length) throws Exception {
		this(sample_rate,filter_length,6,null);
	}

  public XXXAfsk1200(int sample_rate, int filter_length, int emphasis, PacketHandler h) throws Exception {	
  	//transmit_controller = c;
	  for (rate_index=0; rate_index<Afsk1200Filters.sample_rates.length; rate_index++) {
	  	if (Afsk1200Filters.sample_rates[rate_index] == sample_rate) break;
	  }
		if (rate_index == Afsk1200Filters.sample_rates.length) {
			throw new Exception("Sample rate "+sample_rate+" not supported");
		}
			
		handler = h;
		this.sample_rate = sample_rate;
		//his.samples_per_bit = sample_rate / 1200;
		this.samples_per_bit = Afsk1200Filters.bit_periods[rate_index]; // this needs to be computed locally
		//if (samples_per_bit * 1200 != sample_rate) {
		//	throw new Exception("Sample rate must be divisible by 1200");
		//}
		//System.out.printf("%d samples per bit\n",samples_per_bit);
		//x      = new float[samples_per_bit];    
		//u1     = new float[samples_per_bit];    
		//u2     = new float[samples_per_bit];  
		
		float[][][] tdf;
		switch (emphasis) {
		case 0:
  		tdf = Afsk1200Filters.time_domain_filter_none; 
  		break;
		case 6:
  		tdf = Afsk1200Filters.time_domain_filter_full;
  		break;
		default:
			System.err.printf("Filter for de-emphasis of %ddB is not availabe, using 6dB\n",
					emphasis);
			tdf = Afsk1200Filters.time_domain_filter_full;
			break;
		}
		
		for (filter_index=0; filter_index<tdf.length; filter_index++) {
			System.out.printf("Available filter length %d\n",tdf[filter_index][rate_index].length);
			if (filter_length == tdf[filter_index][rate_index].length) {
				System.out.printf("Using filter length %d\n",filter_length);
				break;
			}
		}
		if (filter_index==tdf.length) {
			filter_index=0;
			System.out.printf("Filter length %d not supported, using length %d\n",
					filter_length,
					tdf[filter_index][rate_index].length);
		}
		
		td_filter = tdf[filter_index][rate_index];
		cd_filter = Afsk1200Filters.corr_diff_filter[filter_index][rate_index];
		
		System.out.printf("filter lengths are %d and %d\n",td_filter.length,cd_filter.length);

		x      = new float[td_filter.length];    
		u1     = new float[td_filter.length];    
		//u2     = new float[samples_per_bit];    

		//f0_cos = new float[samples_per_bit];    // f0=1200Hz so we have exactly one cycle.
		//f0_sin = new float[samples_per_bit];
		//f1_cos = new float[6*samples_per_bit]; // f0=2200Hz so 11 cycles fit exactly in 6 bit periods.
		//f1_sin = new float[6*samples_per_bit]; // otherwise we would have had to compute sin/cos

		c0_real = new float[samples_per_bit];
		c0_imag = new float[samples_per_bit];
		c1_real = new float[samples_per_bit];
		c1_imag = new float[samples_per_bit];

		//diff    = new float[samples_per_bit];
		//fdiff   = new float[samples_per_bit];
		diff    = new float[cd_filter.length];
		//fdiff   = new float[corr_diff_filter[rate_index].length]; // can be length 2
		
		phase_inc_f0 = (float) (2.0*Math.PI*1200.0/sample_rate);
		phase_inc_f1 = (float) (2.0*Math.PI*2200.0/sample_rate);
		phase_inc_symbol = (float) (2.0*Math.PI*1200.0/sample_rate);
		//time_inc = (float) (2.0*Math.PI*i/sample_rate);
		
		//for (int i=0; i<6*samples_per_bit; i++) {
		//	float time = (float) (2.0*Math.PI*i/sample_rate);
		//	f1_cos[i] = (float) Math.cos(2200.0*time);
		//	f1_sin[i] = (float) Math.sin(2200.0*time);
		//	if (i>=samples_per_bit) continue;
		//	f0_cos[i] = (float) Math.cos(1200.0*time);
		//	f0_sin[i] = (float) Math.sin(1200.0*time);
		//}
		
		//System.out.printf("Size of symbol sync filter is %d\n", symbol_sync_filter.length);
	}
  
  private volatile boolean data_carrier = false;
  public boolean dcd() { return data_carrier; }

	private float correlation(float[] x, float[] y, int j) {
		float c = (float) 0.0;
		for (int i=0; i<x.length; i++) {
			c += x[j]*y[j];
			j--;
			if (j==-1) j=x.length - 1;
		}
		return c;
	}

	private float sum(float[] x, int j) {
		float c = (float) 0.0;
		for (int i=0; i<x.length; i++) {
			c += x[j];
			j--;
			if (j==-1) j=x.length - 1;
		}
		return c;
	}
	
	private int j_td;   // time domain index 
	private int j_cd;   // time domain index 
	private int j_corr; // correlation index 
	
	private float phase_f0, phase_f1;
	
	//private int j;    // sample index, rolls over each bit period 
	//private int j_f1; // sample index
	private int t; // running sample counter
	
	private float f1cos, f1sin, f0cos, f0sin;

	//public void addSamples(float[] s) {
	//	addSamples(s,s.length);
	//}
	
	private int flag_count = 0;
	private boolean flag_separator_seen = false; // to process the single-bit separation period between flags
	
	private int decode_count = 0;
	
	public void addSamples(float[] s, int n) {
		for (int i=0; i<n; i++) {
			u1[j_td]= s[i];			
			//u2[j] = Filter.filter(u1, j, Filter.BANDPASS_1150_1250_48000_39);
			//x[j]  = Filter.filter(u2, j, Filter.BANDPASS_2150_2250_48000_39);
			//u2[j] = Filter.filter(u1, j, Filter.BANDPASS_1150_1250_48000_39);
			x[j_td]  = Filter.filter(u1, j_td, td_filter);
						
			// compute correlation running value
			//c0_real[j] = x[j_td]*f0_cos[j];
			//c0_imag[j] = x[j_td]*f0_sin[j];
			//
			//c1_real[j] = x[j_td]*f1_cos[j_f1];
			//c1_imag[j] = x[j_td]*f1_sin[j_f1];
			
			c0_real[j_corr] = x[j_td]*(float) Math.cos(phase_f0);
			c0_imag[j_corr] = x[j_td]*(float) Math.sin(phase_f0);
			
			c1_real[j_corr] = x[j_td]*(float) Math.cos(phase_f1);
			c1_imag[j_corr] = x[j_td]*(float) Math.sin(phase_f1);
			
			phase_f0 += phase_inc_f0; if (phase_f0 > (float) 2.0*Math.PI) phase_f0 -= (float) 2.0*Math.PI;
			phase_f1 += phase_inc_f1; if (phase_f1 > (float) 2.0*Math.PI) phase_f1 -= (float) 2.0*Math.PI;

			float cr = sum(c0_real,j_corr);
			float ci = sum(c0_imag,j_corr);
			float c0 = (float) Math.sqrt(cr*cr + ci*ci);

			      cr = sum(c1_real,j_corr);
			      ci = sum(c1_imag,j_corr);
			float c1 = (float) Math.sqrt(cr*cr + ci*ci);
			
			//diff[j_corr] = c0-c1;
			diff[j_cd] = c0-c1;
			//fdiff[j_corr] = Filter.filter(diff,j_corr,Filter.LOWPASS_1200_48000_39);
			//float fdiff = Filter.filter(diff,j_corr,cd_filter);
			float fdiff = Filter.filter(diff,j_cd,cd_filter);

			//System.out.printf("%d %f %f : ",j,diff[j],fdiff[j]);
			//System.out.printf("%d %f %f %f %f : ",j,f0_cos[j],f0_sin[j],f1_cos[j_f1],f1_sin[j_f1]);

			//float previous_fdiff = (j_corr==0) ? fdiff[fdiff.length-1] : fdiff[j_corr-1];
			//if (previous_fdiff*fdiff[j_corr] < 0 || previous_fdiff==0) {
			if (previous_fdiff*fdiff < 0 || previous_fdiff==0) {
				// we found a transition
				int p = t - last_transition;
				last_transition = t;
				
				int bits = (int) Math.round((double) p / (double)samples_per_bit);
				//System.out.printf("$ %f %d\n",(double) p / (double)samples_per_bit,bits);
				
		    if (bits==0 || bits>7) {
	        state=State.WAITING;
	        data_carrier = false;
  				flag_count     = 0;
		    } else {
		    	if (bits==7) {
    				flag_count++;
    				flag_separator_seen=false;
		    		//System.out.printf("Seen %d flags in a row\n",flag_count);

    				data = 0;
		    		bitcount = 0;
		    		switch (state) {
		    		case WAITING:
			    		state=State.JUST_SEEN_FLAG;
			        data_carrier = true;
			    		break;
		    		case JUST_SEEN_FLAG:
  		    		break;
		    		case DECODING:
		    			if (packet!=null && packet.terminate()) {
		    				if (handler!=null)
		    				  handler.handlePacket(packet.bytesWithCRC());
		    				else 
		    					System.out.println(""+(++decode_count)+": "+packet);
		    			}
		    			packet = null;
		    			state=State.JUST_SEEN_FLAG;
		    			break;
		    		}
		    	} else {
		    		switch (state) {
		    		case WAITING:
			    		break;
		    		case JUST_SEEN_FLAG:
		    			state=State.DECODING;
  		    		break;
		    		case DECODING:
		    			break;
		    		}
		    		if (state==State.DECODING) {
		    			if (bits != 1) {
		    				flag_count     = 0;
		    			} else {
		    				if (flag_count>0 && !flag_separator_seen) flag_separator_seen=true;
		    				else {
			    				flag_count     = 0;
		    				}
		    			}
		    			
			    		for (int k=0; k<bits-1; k++) {
			    			bitcount++;
			    			data >>= 1;
			    			data += 128;
			    			if (bitcount==8) {
				    			if (packet==null) packet = new Packet();
			    				if (!packet.addByte((byte) data)) {
			    					state=State.WAITING; 
						        data_carrier = false;
			    				}
			    				//System.out.printf(">>> %02x %c %c\n", data, (char)data, (char)(data>>1));
			    				data = 0;
			    				bitcount = 0;
			    			}
			    		}
			    		if (bits-1 != 5) { // the zero after the ones is not a stuffing
			    			bitcount++;
			    			data >>= 1;
			    			if (bitcount==8) {
				    			if (packet==null) packet = new Packet();
			    				if (!packet.addByte((byte) data)) {
			    					state=State.WAITING; 
						        data_carrier = false;
			    				}
			    				//System.out.printf(">>> %02x %c %c\n", data, (char)data, (char)(data>>1));
			    				data = 0;
			    				bitcount = 0;
			    			}
			    		}
		    		}
		    	}
		    }
			}
			
			previous_fdiff = fdiff;
			
			t++;
			
			j_td++;
			if (j_td==td_filter.length) j_td=0;

			j_cd++;
			if (j_cd==cd_filter.length) j_cd=0;

			j_corr++;
			if (j_corr==samples_per_bit) j_corr=0;

			//j++;
			//if (j==samples_per_bit) j=0;
			
			//j_f1++;
			//if (j_f1==6*samples_per_bit) j_f1=0;
		}
	}
	
	/**************************/
	/*** Packet Transmitter ***/
	/**************************/

	public void setTxDelay(int delay) { tx_delay = delay; };
	public void setTxTail (int delay) { tx_tail  = delay; };
	
	private static enum TxState {
		IDLE,
		PREAMBLE,
		DATA,
		TRAILER
	};
	private TxState tx_state = TxState.IDLE;
	private byte[]  tx_bytes;
	private int     tx_index;
	private int     tx_delay = 20; // default is 20*10ms = 500ms
	private int     tx_tail  = 0;  // obsolete
	private float   tx_symbol_phase, tx_dds_phase;

	private float[] tx_samples;
	private int     tx_last_symbol;
	private int     tx_stuff_count;

	public void prepareToTransmitFlags(int seconds) {
		if (tx_state != TxState.IDLE) {
			System.err.println("Warning: trying to trasmit while Afsk1200 modulator is busy, discarding");
			return;
		}
		tx_bytes = null; // no data
		tx_state = TxState.PREAMBLE;
		tx_index = (int) Math.ceil((double) seconds / (8.0/1200.0)); // number of flags to transmit
		//if (transmit_controller!=null) transmit_controller.startTransmitter();
		tx_symbol_phase = tx_dds_phase = 0.0f;
	}
	
	public void prepareToTransmit(Packet p) {
		if (tx_state != TxState.IDLE) {
			System.err.println("Warning: trying to trasmit while Afsk1200 modulator is busy, discarding");
			return;
		}
		tx_bytes = p.bytesWithCRC(); // This includes the CRC
		tx_state = TxState.PREAMBLE;
		tx_index = (int) Math.ceil(tx_delay * 0.01 / (8.0/1200.0)); // number of flags to transmit
		if (tx_index < 1) tx_index = 1;
		//if (transmit_controller!=null) transmit_controller.startTransmitter();
		tx_symbol_phase = tx_dds_phase = 0.0f;
	}

	public float[] getTxSamplesBuffer() {
		if (tx_samples==null) {
			// each byte makes up to 10 symbols,
			// each symbol takes (1/1200)s to transmit.
			// not sure if it's really necessary to add one.		
			tx_samples = new float[ (int) Math.ceil((10.0/1200.0) * sample_rate) + 1 ];
		}		
		return tx_samples;
	}

  private int generateSymbolSamples(int symbol, float[] s, int position) {
		int count = 0;
		while (tx_symbol_phase < (float) (2.0*Math.PI)) {
			s[position] = (float) Math.sin(tx_dds_phase);
			
			if (symbol==0) tx_dds_phase += phase_inc_f0;
			else           tx_dds_phase += phase_inc_f1;
			
			tx_symbol_phase += phase_inc_symbol;
			
			//if (tx_symbol_phase > (float) (2.0*Math.PI)) tx_symbol_phase -= (float) (2.0*Math.PI);
			if (tx_dds_phase    > (float) (2.0*Math.PI)) tx_dds_phase    -= (float) (2.0*Math.PI);
			
			position++;
			count++;
		}
		
		tx_symbol_phase -= (float) (2.0*Math.PI);

		return count;		
	}
	
	private int byteToSymbols(int bits, boolean stuff) {
		int symbol;
		int position = 0;
		int n;
  	//System.out.printf("byte=%02x stuff=%b\n",bits,stuff);
	  for (int i=0; i<8; i++) {
	  	int bit = bits & 1;
	  	//System.out.println("i="+i+" bit="+bit);
	  	bits = bits >> 1;
	  	if (bit == 0) { // we switch sybols (frequencies)
	  		symbol = (tx_last_symbol == 0) ? 1 : 0;
	  		n = generateSymbolSamples(symbol, tx_samples, position);
	  		position += n;

	  		if (stuff) tx_stuff_count = 0;
	  		tx_last_symbol = symbol;
	  	} else {
	  		symbol = (tx_last_symbol == 0) ? 0 : 1;
	  		n = generateSymbolSamples(symbol, tx_samples, position);
	  		position += n;

	  		if (stuff) tx_stuff_count++;
	  		tx_last_symbol = symbol;
	  		
	  		if (stuff && tx_stuff_count==5) {
	  			// send a zero
	  			//System.out.println("stuffing a zero bit!");
		  		symbol = (tx_last_symbol == 0) ? 1 : 0;
		  		n = generateSymbolSamples(symbol, tx_samples, position);
		  		position += n;

		  		tx_stuff_count = 0;
		  		tx_last_symbol = symbol;
	  		}
	  	}
	  }
	  //System.out.println("generated "+position+" samples");
	  return position;
	}
	
	public int getSamples() {
		int count;
		
		assert(tx_samples != null);

		switch (tx_state) {
		case IDLE: 
			return 0;
		case PREAMBLE:
			count = byteToSymbols(0x7E,false);
						
			tx_index--;
			if (tx_index==0) {
				tx_state = TxState.DATA;
				tx_index = 0;
				tx_stuff_count = 0;
			}
			break;
		case DATA: 
			if (tx_bytes==null) { // we just wanted to transmit tones to adjust the transmitter
				tx_state = TxState.IDLE;
				//if (transmit_controller!=null) transmit_controller.stopTransmitter();
				return 0;
			}
			//System.out.printf("Data byte %02x\n",tx_bytes[tx_index]);
			count = byteToSymbols(tx_bytes[tx_index],true);

			tx_index++;
			if (tx_index==tx_bytes.length) {
				tx_state = TxState.TRAILER;
				if (tx_tail <= 0) { // this should be the normal case
					tx_index = 2;
				} else {
					tx_index = (int) Math.ceil(tx_tail * 0.01 / (8.0/1200.0)); // number of flags to transmit
					if (tx_tail < 2) tx_tail = 2;
				}
			}
			break;
		case TRAILER:
			count = byteToSymbols(0x7E,false);

			tx_index--;
			if (tx_index==0) {
				tx_state = TxState.IDLE;
				//if (transmit_controller!=null) transmit_controller.stopTransmitter();
			}
			break;
		default: 
			assert(false);
			count = -1;
			break;
		}
		
		return count;
	}
}
